通过这个文章可以实现长音频的播放、音量、播放进度控制,以及中断事件的处理和线路切换的响应
一、配置音频会话
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
AVAudioSession *session = [AVAudioSession sharedInstance];
NSError *error;
if ( ![session setCategory:AVAudioSessionCategoryPlayback error:&error] ) {//设置任务类型
NSLog(@"category error log : %@",error.localizedDescription);
}
if ( ![session setActive:YES error:&error] ) {//设置活跃状态
NSLog(@"active error log : %@",error.localizedDescription);
}
return YES;
}
setCategory 说明:
- AVAudioSessionCategoryAmbient 游戏、效率应用程序类型
- AVAudioSessionCategorySoloAmbient 游戏、效率应用程序类型(默认类型)
- AVAudioSessionCategoryPlayback 音频和视频播放器类型
- AVAudioSessionCategoryRecord 录音机、音频捕捉类型
- AVAudioSessionCategoryPlayAndRecord VoIP、语音聊天类型
- AVAudioSessionCategoryAudioProcessing 离线会话和处理类型
- AVAudioSessionCategoryMultiRoute 使用外部硬件的高级A/V应用程序
这里我们使用的是AVAudioSessionCategoryPlayback 类型
二、创建并使用AVAudioPlayer
有两种方法可以创建 AVAudioPlayer,通过NSData创建或者通过本地音频文件的NSURL创建,通过NSURL创建必须是本地路径。这里直接贴代码,功能简单就不做封装了。。。
#import "ViewController.h"
#import <AVFoundation/AVFoundation.h>
#import <QuartzCore/QuartzCore.h>
#define SCREEN_WIDTH [UIScreen mainScreen].bounds.size.width
#define SCREEN_HEIGHT [UIScreen mainScreen].bounds.size.height
@interface ViewController ()<AVAudioPlayerDelegate>
@property(nonatomic,strong)AVAudioPlayer *audioPlayer;
@property(nonatomic,strong)UIButton *playButton;
@property(nonatomic,strong)UISlider *volumeControl;
@property(nonatomic,strong)UISlider *progressControl;
@property(nonatomic,strong)NSTimer *timer;
@end
@implementation ViewController
@synthesize audioPlayer = __audioPlayer;
@synthesize playButton = __playButton;
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
NSError *error;
NSURL *url = [[NSBundle mainBundle] URLForResource:@"晴天" withExtension:@"mp3"];
__audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:&error];
if ( __audioPlayer ) {
__audioPlayer.delegate = self;//设置代理
__audioPlayer.volume = 1.0f;//设置音量
[__audioPlayer prepareToPlay];//初始化准备工作
NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
//注册facetime 电话呼入等中断事件监听
[notificationCenter addObserver:self selector:@selector(handleInterruption:) name:AVAudioSessionInterruptionNotification object:[AVAudioSession sharedInstance]];
//注册线路变化 监听
[notificationCenter addObserver:self selector:@selector(handleRouteChange:) name:AVAudioSessionRouteChangeNotification object:[AVAudioSession sharedInstance]];
}else{
NSLog(@"player init error log %@",error.localizedDescription);
}
[self configView];
}
- (void)configView{
//播放/暂停控制按钮
[self controlButton];
//音量控制
[self volumeControlView];
//进度控制
[self progressControlView];
}
//控制按钮
- (void)controlButton{
__playButton = [UIButton buttonWithType:UIButtonTypeCustom];
__playButton.frame = CGRectMake((SCREEN_WIDTH - 100)/2, 500, 100, 40);
[__playButton setTitle:@"播放" forState:UIControlStateNormal];
[__playButton setTitle:@"停止" forState:UIControlStateSelected];
[__playButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
__playButton.backgroundColor = [UIColor blueColor];
[__playButton addTarget:self action:@selector(audioPlay) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:__playButton];
}
//音量控制
- (void)volumeControlView{
UILabel *label = [[UILabel alloc]initWithFrame:CGRectMake((SCREEN_WIDTH - 300)/2, 370, 80, 20)];
label.text = @"音量控制";
label.textAlignment = NSTextAlignmentCenter;
label.textColor = [UIColor blackColor];
[self.view addSubview:label];
self.volumeControl = [[UISlider alloc]initWithFrame:CGRectMake((SCREEN_WIDTH - 300)/2+100, 375, 200, 10)];
self.volumeControl.maximumValue = 1.0f;
self.volumeControl.minimumValue = 0.0f;
self.volumeControl.value =__audioPlayer.volume;
[self.volumeControl addTarget:self action:@selector(volumeChange:) forControlEvents:UIControlEventValueChanged];
[self.view addSubview:self.volumeControl];
}
//进度控制
- (void)progressControlView{
UILabel *label = [[UILabel alloc]initWithFrame:CGRectMake((SCREEN_WIDTH - 300)/2, 420, 80, 20)];
label.text = @"进度控制";
label.textAlignment = NSTextAlignmentCenter;
label.textColor = [UIColor blackColor];
[self.view addSubview:label];
self.progressControl = [[UISlider alloc]initWithFrame:CGRectMake((SCREEN_WIDTH - 300)/2+100, 425, 200, 10)];
self.progressControl.maximumValue = __audioPlayer.duration;
self.progressControl.minimumValue = 0.0f;
self.progressControl.value = __audioPlayer.currentTime;
[self.progressControl addTarget:self action:@selector(timeChange:) forControlEvents:UIControlEventValueChanged];
[self.view addSubview:self.progressControl];
}
#pragma mark -- ACTION
//监听通知回调事件
- (void)handleInterruption:(NSNotification *)notification{
NSDictionary *info = notification.userInfo;
// NSLog(@"handleInterruption info %@",info);
AVAudioSessionInterruptionType type = [info[AVAudioSessionInterruptionTypeKey] unsignedIntegerValue];
if ( type == AVAudioSessionInterruptionTypeBegan ) {
//任务中断
[self stopPlay];
}else{
//任务开始
AVAudioSessionInterruptionOptions options = [info[AVAudioSessionInterruptionOptionKey] unsignedIntegerValue];
if ( options == AVAudioSessionInterruptionOptionShouldResume ) {//状态恢复
[self startPlay];
}
}
}
//线路变化回调事件
- (void)handleRouteChange:(NSNotification *)notification{
NSDictionary *info = notification.userInfo;
AVAudioSessionRouteChangeReason reason = [info[AVAudioSessionRouteChangeReasonKey] unsignedIntegerValue];
if ( reason == AVAudioSessionRouteChangeReasonOldDeviceUnavailable ) {//之前播放的设备不能使用
AVAudioSessionRouteDescription *previousRoute = info [AVAudioSessionRouteChangePreviousRouteKey];//获取以前的播放线路
AVAudioSessionPortDescription *previousOutput = previousRoute.outputs[0];//获取线路输出设备
NSString *portType = previousOutput.portType;//线路接口类型
if ( [portType isEqualToString:AVAudioSessionPortHeadphones] ) {//耳机或者耳机输出类型
[self stopPlay];//断开耳机,停止播放
}
}
if ( reason == AVAudioSessionRouteChangeReasonNewDeviceAvailable ) {//新的设备接入
[self startPlay];//开始播放
}
}
//更新播放进度条
- (void)updateProgress{
__block typeof(*&self) wself = self;
dispatch_async(dispatch_get_main_queue(), ^{
[wself.progressControl setValue:wself->__audioPlayer.currentTime animated:YES];
});
}
//音量控制事件
- (void)volumeChange:(UISlider *)slider{
__audioPlayer.volume = slider.value;
}
//播放时间控制事件
- (void)timeChange:(UISlider *)slider{
__audioPlayer.currentTime = slider.value;
}
//按钮点击事件
- (void)audioPlay{
if ( !__audioPlayer.isPlaying && !__playButton.selected ) {
[self startPlay];
}else{
[self stopPlay];
}
}
//开始播放
- (void)startPlay{
__block typeof(*&self) wself = self;
dispatch_async(dispatch_get_main_queue(), ^{
wself->__playButton.selected = YES;
});
[__audioPlayer play];
if ( !self.timer ) {
__weak typeof(*&self) wself = self;
//设置1s 调用一次,cpu 占用率最低
self.timer = [NSTimer scheduledTimerWithTimeInterval:1 repeats:YES block:^(NSTimer * _Nonnull timer) {
[wself updateProgress];
}];
}
}
//停止播放
- (void)stopPlay{
__block typeof(*&self) wself = self;
dispatch_async(dispatch_get_main_queue(), ^{
wself->__playButton.selected = NO;
});
[__audioPlayer pause];//暂停
if ( self.timer ) {
[self.timer invalidate];
self.timer = nil;
}
}
#pragma mark -- AVAudioPlayerDelegate
//播放完成
- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag{
if ( flag ) {
__playButton.selected = NO;
}
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
[[NSNotificationCenter defaultCenter] removeObserver:self];
// Dispose of any resources that can be recreated.
}
@end
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。